package com.exm.collectcodenew.juc.aqs;
//回环屏障可以让一组线程全部到达一个状态后再全部同时执行。这里之所以叫作回环是因为当所有等待线程执行完毕，并重置CyclicBarrier 的状态后它可以被重用。
// 之所以叫作屏障是因为线程调用await方法后就会被阻塞，这个阻塞点就称为屏障点，等所有线程都调用了await方法后，线程们就会冲破屏障，继续向下运行。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
//流程：1. 新建⼀个栅栏，第⼀个参数num是线程个数，第二个参数是栅栏需要执行的任务；
//2. 启动10个线程，每个线程传⼊栅栏变量，这10个线程开始执行，然后都阻塞在barrier.await()，大家都在等待最后一个线程的到达；
//3. 当最后⼀个线程到达barrier.await()后，阻塞放开，开始执行栅栏中的方法。
public class CyclicBarrierWorker implements Runnable {
    private int id;
    private CyclicBarrier barrier;
    public CyclicBarrierWorker(int id, final CyclicBarrier barrier) {
        this.id = id;
        this.barrier = barrier;
    }
    @Override
    public void run() {
        try {
            if (id == 5) {
            // 让第5个线程sleep 10秒
                Thread.sleep(10000);
            }
            System.out.println(id + " people wait");
            barrier.await(); // 大家等待最后一个线程到达
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
class TestCyclicBarrier {
    public static void main(String[] args) {
        int num = 10;
        // 新建一个栅栏
        CyclicBarrier barrier = new CyclicBarrier(num, new Runnable() {
            @Override
            public void run() {
        // num个线程全部执行完毕，且都调用barrier.await()，才会去执行该方法
        // 可以理解为计数器初始值为num，每调用一次barrier.await()，计数器-1，直到计数器等于0
                System.out.println("go on together!");
            }
        });
        for (int i = 1; i <= num; i++) {
            new Thread(new CyclicBarrierWorker(i, barrier)).start();
        }
    }
}

